/*jslint vars: true, forin: true, sloppy: true */
/*global probe, angular */
probe.controller('Main', function ($scope, $timeout, $element, $document,
									$filter, $window, ocDialog, scriptEngine,
									GET_FRAME, ocAPI, Capture) {
	var DI = ocDialog.queryDI($element),
		$area = angular.element('<div class="trigger area"></div>'),
		$cm = null,
		shareData = function () {
			return {
				ins: $scope.simpleCase.instructions,
				index: $scope.insControl.selected,
				dictionary: $scope.dictionary,
				edit: false,
				refresh: function () {
					$scope.refresh.insList = !$scope.refresh.insList;
					updateCodePreview();
				}
			};
		},
		previousLine = 0;//code mirror instance

	DI.$$scope.buttons = [
		{
			className: 'simulation',
			fn: function () {
				$scope.fuck3 = "fuck simulation";
			}
		},
		{
			className: 'api',
			fn: function () {
				$scope.fuck3 = "fuck api";
			}
		},
		{
			className: 'regression',
			fn: function () {
				$scope.fuck3 = "fuck monkey";
			}
		},
		{
			className: 'monkey',
			fn: function () {
				$scope.fuck3 = "fuck monkey";
			}
		},
		{
			className: 'availability',
			fn: function () {
				$scope.fuck3 = "fuck monkey";
			}
		},
		{
			className: 'taskmode',
			fn: function () {
				$scope.fuck3 = "fuck monkey";
			}
		}
	];

	$scope.menu = [
		{
			title: '文件(F)',
			menu: [
				{
					title: '新建(N)',
					attr: 'oc-alert-open="newCase"'
				},
				{
					title: '打开(O)',
					attr: 'ng-click="openCase()"'
				},
				null,
				{
					title: '保存(S)',
					attr: 'ng-click="saveCase()"'
				},
				{
					title: '另存为',
					attr: 'ng-click="saveAsCase()"'
				},
				null,
				{
					title: '关闭探针(X)',
					attr: 'oc-dialog-close'
				}
			]
		},
		{
			title: '编辑(E)',
			menu: [
				{
					title: '撤销',
					attr: 'ng-click="undo()" ng-disabled="simple"'
				},
				{
					title: '重复',
					attr: 'ng-click="redo()" ng-disabled="simple"'
				},
				null,
				{
					title: '删除',
					attr: 'ng-click="deleteIns()"'
				},
				{
					title: '全部删除',
					attr: 'oc-alert-open="trashCase"'
				},
				null,
				{
					title: '追加',
					sub: [
						{
							title: '等待',
							attr: 'oc-dialog-open="addWait" ng-disabled="!simple"'
						},
						{
							title: '动作',
							attr: 'oc-dialog-open="addAction" ng-disabled="!simple"'
						},
						{
							title: '断言',
							attr: 'oc-dialog-open="addAssert" ng-disabled="!simple"'
						}
					]
				}
			]
		},
		{
			title: '视图(V)',
			menu: [
				{
					title: '平铺工作区',
					attr: 'ng-click="isProjectFull=true"'
				},
				null,
				{
					title: '显示用例编辑栏',
					attr: 'ng-click="isInactive=false" ng-show="isInactive"'
				},
				{
					title: '隐藏用例编辑栏',
					attr: 'ng-click="isInactive=true" ng-hide="isInactive"'
				}
			]
		},
		{
			title: '对象(E)',
			menu: [
				{
					title: '字典管理器',
					attr: 'oc-dialog-open="openDictionaryEditor"'
				},
				{
					title: '子过程',
					attr: 'disabled'
				},
				{
					title: '元件库',
					attr: 'oc-dialog-open="objetEditor"'
				}
			]
		},
		{
			title: '帮助(H)',
			menu: [
				{
					title: '探针文档',
                    attr:  'oc-dialog-open="probeDoc"'
				},
				{
					title: '测试管理服务',
                    attr:  'oc-dialog-open="testManagementService"'
				},
				{
					title: 'LemonCase语言',
                    attr:  'oc-dialog-open="lemonCase"'
				},
				null,
				{
					title: '关于LemonceProbe',
					attr: 'oc-dialog-open="about"'
				}
			]
		}
	];
	$scope.about = {
		name: 'help/about'
	};

	$scope.lemonCase = {
		name: 'help/lemonCase'
	};

	$scope.probeDoc = {
		name: 'help/probeDoc'
	};

	$scope.testManagementService = {
		name: 'help/testManagementService'
	};

	$scope.openDictionaryEditor = {
		name: 'dictionary/management'
	};

	$scope.objetEditor = {
		name: 'object/editor'
	};

	// 边栏的编辑 初始化
	$scope.refresh = {
		cm: true,
		insList: true
	};
	$scope.tabControl = {
		selected: 0
	};
	$scope.simple = true;
	$scope.simpleCase = {
		origin: 'about:blank',
		noOrigin: false,
		maxLoop: 100,
		nextLoopDelay: 3000,
		//the instruction list should be empty at start
		instructions: []
	};
	$scope.insControl = {
		header: [
			{
				key: 'ins',
				text: '指令',
				width: 80
			},
			{
				key: 'abst',
				text: '指令描述',
				width: 280
			}
		],
		selected: -1
	};

	$scope.status = '';
	$scope['case'] = {};
	$scope['case'].cp = null;
	$scope['case'].caseId = null;
	$scope['case'].code = $filter('toSourceCode')($scope.simpleCase);
	$scope['case'].name = '';
	$scope['case'].comment = '';

	$scope.fillOrigin = function () {
		$scope.simpleCase.origin =
			GET_FRAME().contentWindow.location.href;
	};

	function toCodingMode() {
		$scope.simple = false;
		$scope.editorOptions.readOnly = false;
		//remove unnecessary _0, replace '//simple case' with ''
		$scope['case'].code = $filter('toSourceCode')($scope.simpleCase, true).replace('//simple case\n', '');
		$scope.refresh.cm = !$scope.refresh.cm;
	}
	function resetToSimple() {
		$scope.simple = true;
		$scope.editorOptions.readOnly = true;
		//reset ins
		$scope.simpleCase.instructions.length = 0;
		//reset origin
		$scope.fillOrigin();
		//reset mod
		$scope.viewCoding = false;
	}
	function updateCodePreview() {
		$scope['case'].code = $filter('toSourceCode')($scope.simpleCase);
		$scope.refresh.cm = !$scope.refresh.cm;
	}
	$scope.newCase = {
		title: '新建',
		message: '您未保存的用例将会被丢弃',
		callFn: resetToSimple
	};
	$scope.deleteCase = {
		title: '删除',
		message: '您当前的用例会被删除',
		callFn: function () {
			if (angular.isNumber($scope['case'].caseId)) {
				ocAPI.use('deleteCase').by($scope['case'].caseId).then(function () {
					resetToSimple();
				}, function (err) {
					console.error(err);
				});
			}
		}
	};

	function openCaseSuccess(data) {
		//this = DI of ocFile window
		this.closeDialog();
		$scope['case'] = angular.extend($scope['case'], data['case']);
		var result = $filter("decodeSave")(data['case'].code);

		if (result.simple) {
			resetToSimple();
			$scope.simpleCase = result.out;
			//no origin in save
			if (!result.out.origin) {
				result.out.noOrigin = true;
				$scope.fillOrigin();
			}
		} else {
			//jump to coding tab
			$scope.isCodingModel();
			//and switch to coding mode
			toCodingMode();
			//rewrite code
			$scope['case'].code = result.out;
			$scope.refresh.cm = !$scope.refresh.cm;
		}

		if ($scope['case'].dictionaryId) {
			getDictionaryById($scope['case'].dictionaryId);
		}
	}

	function openActionHandler(cases, index) {
		var caseId = cases[index].caseId;
		if (angular.isNumber(index)) {
			ocAPI.use("retrieveCase").by(caseId).then(openCaseSuccess.bind(this));
		}
		//the user did not select anything
	}

	function saveCaseSuccess() {
		//this = DI of ocFile window
		ocDialog.alert({
			title: '保存成功',
			message: '保存成功'
		}, this);
	}

	function saveCaseErr(err) {
		//this = DI of ocFile window
		ocDialog.alert({
			title: '保存失败',
			message: '保存失败' + err
		}, this);
	}

	function saveActionHandler(cases, index, fileName) {
		//update source code before saving
		if ($scope.simple) {
			$scope['case'].code = $filter('toSourceCode')($scope.simpleCase, true);
		}
		//this = DI of ocFile window
		var body = angular.copy($scope['case']);
		body.name = fileName;

		//创建一个仿真测试用例
		ocAPI.use("createCase").by(body)
			.then(saveCaseSuccess.bind(this), saveCaseErr.bind(this));
	}

	function listCase(action, actionFn) {
		ocAPI.use("listCase").by().then(function (data) {
			ocDialog.file({
				action: action,
				title: '仿真测试用例',
				share: function () {
					return data.cases;
				},
				mapUpdatetime: 'updatetime',
				actionFn: actionFn
			}, DI);
		}, function (err) {
			ocDialog.alert({
				title: '获取失败',
				message: '获取测试用例列表时出错，原因：\n' + err
			}, DI);
		});
	}

	$scope.openCase = listCase.bind(this, '打开', openActionHandler);
	$scope.saveAsCase = listCase.bind(this, '保存', saveActionHandler);
	$scope.saveCase = function () {
		if (!$scope['case'].caseId) {
			//no id, use default save as
			$scope.saveAsCase();
		} else {
			//update source code before saving
			if ($scope.simple) {
				$scope['case'].code = $filter('toSourceCode')($scope.simpleCase, true);
			}

			var id = $scope['case'].caseId;
			var body = angular.copy($scope['case']);
			delete body.caseId;

			ocAPI.use("updateCase").by(id, body)
				.then(saveCaseSuccess.bind(DI), saveCaseErr.bind(DI));
		}
	};

	$scope.addWait = {
		name: 'addIns/wait',
		share: shareData
	};
	$scope.addAction = {
		name: 'addIns/action',
		share: shareData
	};
	$scope.addAssert = {
		name: 'addIns/assert',
		share: shareData
	};

	$scope.insControl.visitFn = function (index) {
		var name, current = $scope.simpleCase.instructions[index].TYPE;
		//wait
		if (current === 0) {
			name = 'addIns/wait';
		} else if (current === 1) {
			name = 'addIns/action';
		} else if (current === 2) {
			name = 'addIns/assert';
		}

		ocDialog.getNewDI(name, angular.extend(shareData(), {
			edit: true
		})).then(function (newDI) {
			newDI.openDialogFrom(DI);
		});
	};

	$scope.deleteIns = function () {
		var index = $scope.insControl.selected;
		//nothing is selected
		if (index === -1) {
			return;
		}

		$scope.simpleCase.instructions.splice(index, 1);
		//reset selected after deletion
		$scope.insControl.selected = Math.max(0, index - 1);
	};
	$scope.up = function () {
		var arr = $scope.simpleCase.instructions, index = $scope.insControl.selected;
		//nothing is selected
		if (index === -1) {
			return;
		}
		//insert at previous index, but the index to insert cannot be less than 0
		//as insert at -1 means insert at array.length - 1
		var newIndex = Math.max(0, index - 1);
		//remove an element at current index and insert the element at new index location
		arr.splice(newIndex, 0, arr.splice(index, 1)[0]);

		$scope.insControl.selected = newIndex;
		//
		$scope.refresh.insList = !$scope.refresh.insList;
	};
	$scope.down = function () {
		var arr = $scope.simpleCase.instructions, index = $scope.insControl.selected;
		//nothing is selected
		if (index === -1) {
			return;
		}

		arr.splice(index + 1, 0, arr.splice(index, 1)[0]);
		//don't let selected go over when the last element is selected
		$scope.insControl.selected = Math.min(arr.length - 1, index + 1);
		//
		$scope.refresh.insList = !$scope.refresh.insList;
	};

	$scope.trashCase = {
		title: '警告 - 全部清空',
		message: '您确定要清空整个测试用例吗？',
		callFn: function () {
			$scope.simpleCase.instructions.length = 0;
		}
	};
    $scope.editorOptions = {
        lineWrapping : true,
        lineNumbers: true,
	    matchBrackets: true,
	    mode: "text/x-php",
	    indentWithTabs: true,
	    indentUnit: 4,
	    //can't edit in simple case
	    readOnly: true,
		//automatically refresh
	    autoRefresh: true,
		onLoad: function (cm) {
			$cm = cm;
		}
    };

	$scope.enableCoding = function () {
		ocDialog.alert({
			title: '确认转换',
			message: '启用编辑源码，您当前的用例\n' +
				'将无法使用简单视图编辑。\n' +
				'（建议您先保存一次简单用例，再启用编辑源码）',
			callFn: toCodingMode
		}, DI);
	};

	$scope.parse = function () {
		//reset case before parse
		$scope['case'].cp = null;
		scriptEngine.setup({
			contextFrame: GET_FRAME()
		});

		scriptEngine.parse($scope['case'].code)(function (err, ast) {
			if (err) {
				$scope.parseConsole = err.toString();
			} else {
				$scope.parseConsole = '分析成功：' + angular.toJson(ast, true);
			}
		});
	};
	
	$scope.capture = function () {
		GET_FRAME().style.backgroundColor = '#ffffff';
		Capture.setZIndex(550).setContext(GET_FRAME().contentWindow);
		
		Capture.watchHTML(function (selector) {
			GET_FRAME().style.zIndex = 0;
			GET_FRAME().style.backgroundColor = '';
			
			//insert at current selection
			$cm.replaceSelection('"' + selector + '"');
		});
	};
	$scope.insertField = function () {
		throw new Error("todo");
	};

	$scope.undo = function () {
		$cm.undo();
	};
	$scope.redo = function () {
		$cm.redo();
	};

	$scope.parseConsole = '';

	var successCallback = function () {
		ocDialog.getNewDI('upload', this).then(function (newDI) {
			newDI.openDialogFrom(DI);
		});
		//lift mask
		$scope.mask = false;
		//clean current case
		$scope['case'].cp = null;
	};

	function triggerCallback(objectDOM) {
		if (!$scope.highlightIns) {
			return;//user disabled highlight
		}
		
		var frameOffset = GET_FRAME().getBoundingClientRect();
		var offset = objectDOM.getBoundingClientRect();

		$area.css({
			top: (offset.top + frameOffset.top - 2) + 'px',
			left: (offset.left + frameOffset.left - 2) + 'px',
			width: offset.width + 'px',
			height: offset.height + 'px',
			'background-color': 'rgba(96, 209, 251, 0.9)'
		});

		$document.find('body').append($area);

		$timeout(function () {
			$area.css({'background-color': 'transparent'});
		}, 500);

		$timeout(function () {
			$area.remove();
		}, 1500);
	}

	function runCallback(currentIns) {
		var line = currentIns.LINE;
		if (angular.isNumber(line)) {
			if ($scope.simple) {
				//simple case highlight
				$scope.insControl.selected =
					(currentIns.NAME || '').match(/\d/) || $scope.insControl.selected;
			} else {
				//coding mod highlight
				//highlight line n result in line n+1 being highlighted in cm
				line -= 1;
				//remove previous highlighting
				$cm.removeLineClass(previousLine, 'background');
				$cm.addLineClass(line, 'background', 'current-line');
				previousLine = line;
			}
			
			// $scope.insControl.selected = currentIns.LINE;
		}
	}

	$scope.play = function () {
		if (!$scope['case'].cp) {

			var engineSetup = {
				contextFrame: GET_FRAME(),
				//runExceptionHandle: null,//lemoncase use console.error
				successCallback: successCallback,
				runCallback: runCallback,
				triggerCallback: triggerCallback
			};
			//common setup
			scriptEngine.setup(engineSetup);

			try {
				//simple case
				if ($scope.simple) {
					$scope['case'].code =
						$filter('toSourceCode')($scope.simpleCase);
				}

				scriptEngine
					.getCase($scope['case'].code,
							 $scope.dictionary)(function (err, $cp) {
						if (err) {
							throw err;
						}
						$scope['case'].cp = $cp;
					});
			} catch (e) {
				ocDialog.alert({
					title: '执行引擎启动失败',
					message: '执行引擎启动失败，原因：\n' + e
				}, DI);
				//clean up
				$scope['case'].cp = null;
			}

			$scope['case'].cp.$setState('running')
				.$$bootstrap().$$core().suspend();
		}

		$timeout(function () {
			try {
				$scope['case'].cp.resume();
			} catch (error) {
				ocDialog.alert({
					title: '执行引擎错误',
					message: '执行引擎运行错误，原因：\n' + error
				}, DI);
				//clean up
				$scope['case'].cp = null;
			}
		}, 150);
		$scope.mask = true;
	};
	$scope.pause = function () {
		try {
			$scope['case'].cp.suspend();
		} catch (e) {
			ocDialog.alert({
				title: '暂停失败',
				message: '暂停失败，原因：\n' + e,
				callFn: angular.noop
			}, DI);
		}
	};
	$scope.stop = function () {
		try {
			$scope['case'].cp.stop();
		} catch (e) {
			ocDialog.alert({
				title: '停止失败',
				message: '停止失败，原因：\n' + e,
				callFn: angular.noop
			}, DI);
		} finally {
			//try to clean up
			$scope['case'].cp = null;
		}
		$scope.mask = false;
	};
	$scope.highlightIns = true;

	$scope.$watchCollection('case.cp', function (value) {
		if (!value) {
			//is undefined or null
			$scope.status = '';
			return;
		}

		if (value.$$state) {
			$scope.status = '引擎 - ' +
				value.$$state + ' 第' + (value.$$currentLoop + 1) + '循环';
		}
	});

	$scope.dictionary = {
		name: '未使用'
	};

	function getDictionaryById (id) {
		ocAPI.use('retrieveDictionary').by(id).then(function (data) {
			$scope.dictionary = $filter('getDictionary')(data.dictionary);
			$scope['case'].dictionaryId = id;
		});
	}

	$scope.openDictionary = function () {
		ocAPI.use("listDictionary").by().then(function (data) {
			ocDialog.file({
				action: '打开',
				title: '数据字典',
				share: function () {
					return data.dictionaries;
				},
				mapUpdatetime: 'updatetime',
				actionFn: function (dictionarys, selected) {
					var id = dictionarys[selected].dictionaryId;

					getDictionaryById(id);
					this.closeDialog();
				}
			}, DI);
		});
	};

	// 控制边栏的固定与显隐
	$scope.iframeGrid = {
		right: '20rem'
	};
	$scope.isInactive = false;
	$scope.isFixed = true;
	$scope.togglePanel = function () {
		$scope.isInactive = !$scope.isInactive;
		$scope.isFixed = $scope.isInactive;
		$scope.fixedPanel();
	};
	$scope.fixedPanel = function () {
		$scope.isFixed = !$scope.isFixed;
		$scope.iframeGrid.right = $scope.isFixed ? '20rem' : 0;
	};

	// Iframe的大小控制
	$scope.iframeSize = {
		width: '100%',
		height: '100%'
	};
	$scope.fullScreen = function () {
		$scope.isProjectFull = true;
		$scope.iframeSize.width = '100%';
		$scope.iframeSize.height = '100%';
	};
	$scope.project = {
		width: function (newWidth) {
			var size = $scope.iframeSize;
			if (angular.isDefined(newWidth)) {
				size.width = newWidth.match(/\d+/)[0] + 'px';
			}
			return size.width;
		},
		height: function (newHeight) {
			var size = $scope.iframeSize;
			if (angular.isDefined(newHeight)) {
				size.height = newHeight.match(/\d+/)[0] + 'px';
			}
			return size.height;
		}
	};
	$scope.isProjectFull = true;
	$scope.history = $window.history;
	
	// 简单模式与编码模式切换
	$scope.viewCoding = false;
	$scope.isEasyModel = function () {
		$scope.viewCoding = false;
	};
	$scope.isCodingModel = function () {
		$scope.viewCoding = true;

		//show example code to use if it's simple case
		if ($scope.simple) {
			updateCodePreview();
		}
	};
	//遮罩
	$scope.mask = false;
});
